Skip to content

Conversation

@Udayraj123
Copy link
Owner

@Udayraj123 Udayraj123 commented Sep 29, 2024

Closes multiple feature requests/issues: #156 #128 #125 #105 #39 #185 #247

  • Support for colored outputs! OMRChecker can optionally become colorful with a very small performance overhead :)
  • Showing scores, colored verdicts and symbols from the answer key (credits @palash018)
  • Major refactoring done around read_response and for general code readability
  • Upgraded overall preprocessors structure
  • Upgraded CropOnMarkers plugin to support patch areas, blob detection(for the four corners and more), line detection
  • Upgraded CropPage preprocessor to correct page curvature slightly (ref)
  • Added a top level try catch to mention debug mode
  • Introduces the schema for reading barcodes and sorting files
  • Support for exporting omr metrics (exportable to a JSON object which can be used for visualisations and calculating quality/confidence scores)
  • More refactors:
    • Renamed pageDimensions -> templateDimensions
    • Support for a top level processingImageShape as well as pre-processor level processingImageShape
    • Added conditionalSets in the schema.
    • Rename the fieldType to bubbleFieldType and introduced fieldDetectionType
    • Support multiple images in image utils like resize/normalize, etc
    • support imports in pre-commit hook scripts
    • add auto remove unused imports hook
    • add code coverage module
    • add virtual environment support

Changelogs from #237

  • Support for barcode field(pyzbar)
  • Refactor drawing classes to enable drawing any field types
  • Add a simple launch.json(VScode py debugger)

Changelogs from #186

  • update snapshots using pandas to_string()
  • feat: support for image snapshots
  • feat: use $ref and $def addresses in all schemas
  • refactor drawing utils
  • refactor: detection logic
  • feat: run_sample_fixture
  • feat: working save_image_levels for color and grayscale debug stack images

Changelogs from #192

Fixes #190 and #191
Also addresses: #36

  • feat: separately merge questions, answers and marking schemes from parent
  • feat: basic working conditional set
  • feat: pass matched set name

Other Features covered

  • feat: template roi gui; created local scripts folder as todo; add new template for conditional sets

  • fix: defaultSelector issue

  • feat: support for customFieldTypes in template.json; fix template matching issue

  • Added support for show_preprocessor_diff{} to display per-processor level before-after images (apart from show_image_level)

  • Stabilised autorotate by giving option to crop from preview

  • preview can be enabled for all preprocessors in config.json (autorotating sample is available in Autorotating folder in samples)

Changelogs from #197

  • add Contrast preprocessor
  • add AutoRotate preprocessor
  • rename scan areas to scan zones
  • template alignment using SIFT and delaunay triangulation
  • add phase_correlation_shifts
  • foundation for local scripts
  • support for output_mode==moderation
  • support for section-wise streak marking in evaluation
  • fixed utf character issue in windows
  • add coverage module

Current Master branch:

~35 Files, 4441 loc == Avg 126.8 lines per file, yet highly coupled code and restricted to bubble fields.

After code merge

~112 Files, 16000 loc == Avg 142.8 lines per file, Yet much more readable, more extensible and full of features.

Udayraj123 and others added 30 commits March 23, 2024 19:39
…_image_shape

feat: complete marked bubbles on colored images
fix: debugging help

fix: threshold hack
fix: py version

fix: env class

fix: ut issues

fix: timezone issue

fix: timezone issue
@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Sep 7, 2025

CI Feedback 🧐

(Feedback updated until commit 2a18bf6)

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Test and Coverage (3.11)

Failed stage: Run pytest (with TZ=Asia/Kolkata) [❌]

Failed test name: src/tests/test_all_samples.py::test_run_omr_marker

Failure summary:

Multiple pytest tests failed due to snapshot mismatches and an output DataFrame content mismatch:
-
Image snapshot mismatches (asserted via assert_image_snapshot in src/tests/utils.py:127):
-
src/tests/test_all_samples.py::test_run_omr_marker failed at src/tests/test_all_samples.py:16
because src/tests/image_snapshots/camscanner-1.jpg did not match
outputs/2-omr-marker/ScanBatch1/CheckedOMRs/camscanner-1.jpg (Assertion at
src/tests/fixtures/pytest_image_snapshot.py:88).
-
src/tests/test_all_samples.py::test_run_bonus_marking_grouping failed at
src/tests/test_all_samples.py:36 because src/tests/image_snapshots/IMG_20201116_143512.jpg did
not match outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/IMG_20201116_143512.jpg (Assertion
at src/tests/fixtures/pytest_image_snapshot.py:88).
-
src/tests/test_all_samples.py::test_run_answer_key_using_image_grouping failed at
src/tests/test_all_samples.py:61 because src/tests/image_snapshots/angle-1.jpg did not match
outputs/3-answer-key/using-image-grouping/CheckedOMRs/angle-1.jpg (Assertion at
src/tests/fixtures/pytest_image_snapshot.py:88).
- Data snapshot/content mismatch:
-
src/tests/test_all_samples.py::test_run_template_shifts failed at src/tests/test_all_samples.py:87
with AssertionError: assert [- snapshot] == [+ received] because the generated results (including
fields like Booklet_No) differed from the expected snapshot; e.g., expected Booklet_No values
1033/157344 vs received 13/15334.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

322:  UV_PYTHON: 3.11
323:  UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
324:  OMR_CHECKER_CONTAINER: true
325:  TZ: Asia/Kolkata
326:  ##[endgroup]
327:  ============================= test session starts ==============================
328:  platform linux -- Python 3.11.13, pytest-8.4.1, pluggy-1.6.0
329:  rootdir: /home/runner/work/OMRChecker/OMRChecker
330:  configfile: pytest.ini
331:  testpaths: src/tests
332:  plugins: syrupy-4.6.1, cov-6.2.1, mock-3.14.0
333:  collected 34 items
334:  src/tests/test_all_samples.py .F.F..F....F.......                        [ 55%]
335:  src/tests/test_edge_cases.py ...                                         [ 64%]
336:  src/tests/test_template_validations.py ............                      [100%]
337:  =================================== FAILURES ===================================
338:  _____________________________ test_run_omr_marker ______________________________
...

350:  # Check image snapshots
351:  # Note: image snapshots are updated using the --image-snapshot-update flag
352:  output_relative_dir = "outputs/2-omr-marker/ScanBatch1/CheckedOMRs"
353:  >       assert_image_snapshot(output_relative_dir, "camscanner-1.jpg", image_snapshot)
354:  src/tests/test_all_samples.py:16: 
355:  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
356:  src/tests/utils.py:127: in assert_image_snapshot
357:  image_snapshot(output_path, IMAGE_SNAPSHOTS_PATH.joinpath(image_path))
358:  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
359:  source_image_path = PosixPath('outputs/2-omr-marker/ScanBatch1/CheckedOMRs/camscanner-1.jpg')
360:  snapshot_path = PosixPath('src/tests/__image_snapshots__/camscanner-1.jpg')
361:  def _image_snapshot(source_image_path, snapshot_path) -> None:
362:  source_image_path, snapshot_path = Path(source_image_path), Path(snapshot_path)
363:  config = request.config
364:  update_snapshots = config.getoption("--image-snapshot-update")
365:  show_on_fail = config.getoption("--show-images-on-fail")
366:  source_image = open_image(source_image_path)
367:  if not update_snapshots and snapshot_path.exists():
368:  current_snapshot = open_image(snapshot_path)
369:  # source_image, current_snapshot = extend_to_match_size(source_image, current_snapshot)
370:  diff_score = image_diff(source_image, current_snapshot)
371:  if diff_score != 0:
372:  if show_on_fail is True:
373:  cv2.imshow("diff", cv2.subtract(source_image, current_snapshot))
374:  cv2.imshow("current_snapshot", current_snapshot)
375:  # TODO: fix code is not waiting despite unmocking mocker
376:  close_all_on_wait_key()
377:  msg = f"{snapshot_path}: Snapshot does not match the image {source_image_path}"
378:  >               raise AssertionError(msg)
379:  E               AssertionError: src/tests/__image_snapshots__/camscanner-1.jpg: Snapshot does not match the image outputs/2-omr-marker/ScanBatch1/CheckedOMRs/camscanner-1.jpg
380:  src/tests/__fixtures__/pytest_image_snapshot.py:88: AssertionError
381:  ----------------------------- Captured stdout call -----------------------------
...

393:  outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stack           
394:  INFO     Created :                                         file.py:70
395:  outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stack           
396:  /colored                                                    
397:  INFO     Created :                                         file.py:70
398:  outputs/2-omr-marker/ScanBatch2/CheckedOMRs/_MULT           
399:  I_                                                          
400:  INFO     Created :                                         file.py:70
401:  outputs/2-omr-marker/ScanBatch2/CheckedOMRs/_MULT           
402:  I_/colored                                                  
403:  INFO     Created : outputs/2-omr-marker/ScanBatch2/Manual  file.py:79
404:  INFO     Created :                                         file.py:79
405:  outputs/2-omr-marker/ScanBatch2/Manual/MultiMarke           
406:  dFiles                                                      
407:  INFO     Created :                                         file.py:79
408:  outputs/2-omr-marker/ScanBatch2/Manual/ErrorFiles           
409:  INFO     Created : outputs/2-omr-marker/ScanBatch2/Results file.py:90
410:  INFO     Created :                                         file.py:90
411:  outputs/2-omr-marker/ScanBatch2/ImageMetrics                
412:  INFO     Created :                                         file.py:90
413:  outputs/2-omr-marker/ScanBatch2/Evaluations                 
414:  INFO     Checking Files...                    directory_handler.py:32
415:  INFO     Created new file:                    directory_handler.py:60
416:  'outputs/2-omr-marker/ScanBatch2/Res                        
417:  ults/Results_05AM.csv'                                      
418:  INFO     Created new file:                    directory_handler.py:60
419:  'outputs/2-omr-marker/ScanBatch2/Man                        
420:  ual/MultiMarkedFiles.csv'                                   
421:  INFO     Created new file:                    directory_handler.py:60
422:  'outputs/2-omr-marker/ScanBatch2/Man                        
423:  ual/ErrorFiles.csv'                                         
424:  INFO                                                      entry.py:44
...

591:  INFO     Saving Image to                                  image.py:55
592:  'outputs/2-omr-marker/ScanBatch2/CheckedOMRs/col            
593:  ored/camscanner-2.jpg'                                      
594:  INFO     Gray Stack level: 1 ['Input Image', 'Marked      file.py:130
595:  Template']                                                  
596:  INFO     Saved stack image to:                            file.py:136
597:  outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stac            
598:  k/camscanner-2_1_stack.jpg                                  
599:  INFO     Colored Stack level: 1 ['Input Image', 'Marked   file.py:144
600:  Template']                                                  
601:  INFO     Saved colored stack image to:                    file.py:154
602:  outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stac            
603:  k/colored/camscanner-2_1_stack.jpg                          
604:  DEBUG    Closed file Results                  directory_handler.py:77
605:  DEBUG    Closed file MultiMarked              directory_handler.py:77
606:  DEBUG    Closed file Errors                   directory_handler.py:77
607:  INFO                                                     entry.py:487
...

628:  outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stack           
629:  INFO     Created :                                         file.py:70
630:  outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stack           
631:  /colored                                                    
632:  INFO     Created :                                         file.py:70
633:  outputs/2-omr-marker/ScanBatch1/CheckedOMRs/_MULT           
634:  I_                                                          
635:  INFO     Created :                                         file.py:70
636:  outputs/2-omr-marker/ScanBatch1/CheckedOMRs/_MULT           
637:  I_/colored                                                  
638:  INFO     Created : outputs/2-omr-marker/ScanBatch1/Manual  file.py:79
639:  INFO     Created :                                         file.py:79
640:  outputs/2-omr-marker/ScanBatch1/Manual/MultiMarke           
641:  dFiles                                                      
642:  INFO     Created :                                         file.py:79
643:  outputs/2-omr-marker/ScanBatch1/Manual/ErrorFiles           
644:  INFO     Created : outputs/2-omr-marker/ScanBatch1/Results file.py:90
645:  INFO     Created :                                         file.py:90
646:  outputs/2-omr-marker/ScanBatch1/ImageMetrics                
647:  INFO     Created :                                         file.py:90
648:  outputs/2-omr-marker/ScanBatch1/Evaluations                 
649:  INFO     Checking Files...                    directory_handler.py:32
650:  INFO     Created new file:                    directory_handler.py:60
651:  'outputs/2-omr-marker/ScanBatch1/Res                        
652:  ults/Results_05AM.csv'                                      
653:  INFO     Created new file:                    directory_handler.py:60
654:  'outputs/2-omr-marker/ScanBatch1/Man                        
655:  ual/MultiMarkedFiles.csv'                                   
656:  INFO     Created new file:                    directory_handler.py:60
657:  'outputs/2-omr-marker/ScanBatch1/Man                        
658:  ual/ErrorFiles.csv'                                         
659:  INFO                                                      entry.py:44
...

858:  INFO     Saving Image to                                  image.py:55
859:  'outputs/2-omr-marker/ScanBatch1/CheckedOMRs/col            
860:  ored/camscanner-1.jpg'                                      
861:  INFO     Gray Stack level: 1 ['Input Image', 'Marked      file.py:130
862:  Template']                                                  
863:  INFO     Saved stack image to:                            file.py:136
864:  outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stac            
865:  k/camscanner-1_1_stack.jpg                                  
866:  INFO     Colored Stack level: 1 ['Input Image', 'Marked   file.py:144
867:  Template']                                                  
868:  INFO     Saved colored stack image to:                    file.py:154
869:  outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stac            
870:  k/colored/camscanner-1_1_stack.jpg                          
871:  DEBUG    Closed file Results                  directory_handler.py:77
872:  DEBUG    Closed file MultiMarked              directory_handler.py:77
873:  DEBUG    Closed file Errors                   directory_handler.py:77
874:  INFO                                                     entry.py:487
...

887:  Tip: To see some awesome visuals, increase                  
888:  `outputs.show_image_level` in your config:                  
889:  'samples/2-omr-marker/config.json'                          
890:  ------------------------------ Captured log call -------------------------------
891:  INFO     src.utils.logger:validations.py:85 Loading config.json: samples/2-omr-marker/config.json
892:  INFO     src.utils.logger:validations.py:50 Loading template.json: samples/2-omr-marker/template.json
893:  INFO     src.utils.logger:validations.py:12 Loading evaluation.json: samples/2-omr-marker/evaluation.json
894:  INFO     src.utils.logger:file.py:56 Checking Directories...
895:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch2/CheckedOMRs/colored
896:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stack
897:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stack/colored
898:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch2/CheckedOMRs/_MULTI_
899:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch2/CheckedOMRs/_MULTI_/colored
900:  INFO     src.utils.logger:file.py:79 Created : outputs/2-omr-marker/ScanBatch2/Manual
901:  INFO     src.utils.logger:file.py:79 Created : outputs/2-omr-marker/ScanBatch2/Manual/MultiMarkedFiles
902:  INFO     src.utils.logger:file.py:79 Created : outputs/2-omr-marker/ScanBatch2/Manual/ErrorFiles
903:  INFO     src.utils.logger:file.py:90 Created : outputs/2-omr-marker/ScanBatch2/Results
904:  INFO     src.utils.logger:file.py:90 Created : outputs/2-omr-marker/ScanBatch2/ImageMetrics
905:  INFO     src.utils.logger:file.py:90 Created : outputs/2-omr-marker/ScanBatch2/Evaluations
906:  INFO     src.utils.logger:directory_handler.py:32 Checking Files...
907:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/2-omr-marker/ScanBatch2/Results/Results_05AM.csv'
908:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/2-omr-marker/ScanBatch2/Manual/MultiMarkedFiles.csv'
909:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/2-omr-marker/ScanBatch2/Manual/ErrorFiles.csv'
910:  INFO     src.utils.logger:entry.py:44 
...

927:  parsed_destination_points=[[  0.   0.]
928:  [325.   0.]
929:  [325. 449.]
930:  [  0. 449.]] 
931:  warped_dimensions=(325, 449)
932:  DEBUG    src.utils.logger:interpretation_pass.py:62 Thresholding: 	 file_level_fallback_threshold: 167.7 	global_std_THR: 10	
933:  INFO     src.utils.logger:entry.py:333 (/1) Graded with score: 55.0	 Correct: 22 Incorrect: 0 Unmarked: 0 	 file: 'camscanner-2.jpg'
934:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/2-omr-marker/ScanBatch2/CheckedOMRs/camscanner-2.jpg'
935:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/2-omr-marker/ScanBatch2/CheckedOMRs/colored/camscanner-2.jpg'
936:  INFO     src.utils.logger:file.py:130 Gray Stack level: 1 ['Input Image', 'Marked Template']
937:  INFO     src.utils.logger:file.py:136 Saved stack image to: outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stack/camscanner-2_1_stack.jpg
938:  INFO     src.utils.logger:file.py:144 Colored Stack level: 1 ['Input Image', 'Marked Template']
939:  INFO     src.utils.logger:file.py:154 Saved colored stack image to: outputs/2-omr-marker/ScanBatch2/CheckedOMRs/stack/colored/camscanner-2_1_stack.jpg
940:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Results
941:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file MultiMarked
942:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Errors
943:  INFO     src.utils.logger:entry.py:487 
...

947:  INFO     src.utils.logger:entry.py:491 Total file(s) processed    : 1 (Sum Tallied!)
948:  INFO     src.utils.logger:entry.py:496 
949:  Finished Checking 1 file(s) in 1 seconds i.e. ~0.0 minute(s).
950:  INFO     src.utils.logger:entry.py:499 OMR Processing Rate        : 	 ~ 1.0 seconds/OMR
951:  INFO     src.utils.logger:entry.py:502 OMR Processing Speed       : 	 ~ 60.0 OMRs/minute
952:  INFO     src.utils.logger:entry.py:173 
953:  Tip: To see some awesome visuals, increase `outputs.show_image_level` in your config: 'samples/2-omr-marker/config.json'
954:  INFO     src.utils.logger:file.py:56 Checking Directories...
955:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch1/CheckedOMRs/colored
956:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stack
957:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stack/colored
958:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch1/CheckedOMRs/_MULTI_
959:  INFO     src.utils.logger:file.py:70 Created : outputs/2-omr-marker/ScanBatch1/CheckedOMRs/_MULTI_/colored
960:  INFO     src.utils.logger:file.py:79 Created : outputs/2-omr-marker/ScanBatch1/Manual
961:  INFO     src.utils.logger:file.py:79 Created : outputs/2-omr-marker/ScanBatch1/Manual/MultiMarkedFiles
962:  INFO     src.utils.logger:file.py:79 Created : outputs/2-omr-marker/ScanBatch1/Manual/ErrorFiles
963:  INFO     src.utils.logger:file.py:90 Created : outputs/2-omr-marker/ScanBatch1/Results
964:  INFO     src.utils.logger:file.py:90 Created : outputs/2-omr-marker/ScanBatch1/ImageMetrics
965:  INFO     src.utils.logger:file.py:90 Created : outputs/2-omr-marker/ScanBatch1/Evaluations
966:  INFO     src.utils.logger:directory_handler.py:32 Checking Files...
967:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/2-omr-marker/ScanBatch1/Results/Results_05AM.csv'
968:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/2-omr-marker/ScanBatch1/Manual/MultiMarkedFiles.csv'
969:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/2-omr-marker/ScanBatch1/Manual/ErrorFiles.csv'
970:  INFO     src.utils.logger:entry.py:44 
...

987:  parsed_destination_points=[[  0.   0.]
988:  [325.   0.]
989:  [325. 449.]
990:  [  0. 449.]] 
991:  warped_dimensions=(325, 449)
992:  DEBUG    src.utils.logger:interpretation_pass.py:62 Thresholding: 	 file_level_fallback_threshold: 187.3 	global_std_THR: 17.39	
993:  INFO     src.utils.logger:entry.py:333 (/1) Graded with score: -4.0	 Correct: 5 Incorrect: 16 Unmarked: 1 	 file: 'camscanner-1.jpg'
994:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/2-omr-marker/ScanBatch1/CheckedOMRs/camscanner-1.jpg'
995:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/2-omr-marker/ScanBatch1/CheckedOMRs/colored/camscanner-1.jpg'
996:  INFO     src.utils.logger:file.py:130 Gray Stack level: 1 ['Input Image', 'Marked Template']
997:  INFO     src.utils.logger:file.py:136 Saved stack image to: outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stack/camscanner-1_1_stack.jpg
998:  INFO     src.utils.logger:file.py:144 Colored Stack level: 1 ['Input Image', 'Marked Template']
999:  INFO     src.utils.logger:file.py:154 Saved colored stack image to: outputs/2-omr-marker/ScanBatch1/CheckedOMRs/stack/colored/camscanner-1_1_stack.jpg
1000:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Results
1001:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file MultiMarked
1002:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Errors
1003:  INFO     src.utils.logger:entry.py:487 
1004:  INFO     src.utils.logger:entry.py:488 Total file(s) moved        : 0
1005:  INFO     src.utils.logger:entry.py:489 Total file(s) not moved    : 1
1006:  INFO     src.utils.logger:entry.py:490 --------------------------------
1007:  INFO     src.utils.logger:entry.py:491 Total file(s) processed    : 1 (Sum Tallied!)
1008:  INFO     src.utils.logger:entry.py:496 
1009:  Finished Checking 1 file(s) in 1 seconds i.e. ~0.0 minute(s).
1010:  INFO     src.utils.logger:entry.py:499 OMR Processing Rate        : 	 ~ 1.0 seconds/OMR
1011:  INFO     src.utils.logger:entry.py:502 OMR Processing Speed       : 	 ~ 60.0 OMRs/minute
1012:  INFO     src.utils.logger:entry.py:173 
1013:  Tip: To see some awesome visuals, increase `outputs.show_image_level` in your config: 'samples/2-omr-marker/config.json'
1014:  _______________________ test_run_bonus_marking_grouping ________________________
1015:  run_sample = <function run_sample_fixture.<locals>.run_sample at 0x7fd5a1ab6b60>
1016:  mocker = <pytest_mock.plugin.MockerFixture object at 0x7fd5a2f77fd0>
1017:  snapshot = dict({
1018:  'Manual/ErrorFiles.csv': '''
1019:  Empty DataFrame
...

1031:  output_relative_dir = f"outputs/{sample_path}/CheckedOMRs"
1032:  >       assert_image_snapshot(
1033:  output_relative_dir, "IMG_20201116_143512.jpg", image_snapshot
1034:  )
1035:  src/tests/test_all_samples.py:36: 
1036:  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
1037:  src/tests/utils.py:127: in assert_image_snapshot
1038:  image_snapshot(output_path, IMAGE_SNAPSHOTS_PATH.joinpath(image_path))
1039:  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
1040:  source_image_path = PosixPath('outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/IMG_20201116_143512.jpg')
1041:  snapshot_path = PosixPath('src/tests/__image_snapshots__/IMG_20201116_143512.jpg')
1042:  def _image_snapshot(source_image_path, snapshot_path) -> None:
1043:  source_image_path, snapshot_path = Path(source_image_path), Path(snapshot_path)
1044:  config = request.config
1045:  update_snapshots = config.getoption("--image-snapshot-update")
1046:  show_on_fail = config.getoption("--show-images-on-fail")
1047:  source_image = open_image(source_image_path)
1048:  if not update_snapshots and snapshot_path.exists():
1049:  current_snapshot = open_image(snapshot_path)
1050:  # source_image, current_snapshot = extend_to_match_size(source_image, current_snapshot)
1051:  diff_score = image_diff(source_image, current_snapshot)
1052:  if diff_score != 0:
1053:  if show_on_fail is True:
1054:  cv2.imshow("diff", cv2.subtract(source_image, current_snapshot))
1055:  cv2.imshow("current_snapshot", current_snapshot)
1056:  # TODO: fix code is not waiting despite unmocking mocker
1057:  close_all_on_wait_key()
1058:  msg = f"{snapshot_path}: Snapshot does not match the image {source_image_path}"
1059:  >               raise AssertionError(msg)
1060:  E               AssertionError: src/tests/__image_snapshots__/IMG_20201116_143512.jpg: Snapshot does not match the image outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/IMG_20201116_143512.jpg
1061:  src/tests/__fixtures__/pytest_image_snapshot.py:88: AssertionError
1062:  ----------------------------- Captured stdout call -----------------------------
...

1081:  edOMRs/stack/colored                                        
1082:  INFO     Created :                                         file.py:70
1083:  outputs/3-answer-key/bonus-marking-grouping/Check           
1084:  edOMRs/_MULTI_                                              
1085:  INFO     Created :                                         file.py:70
1086:  outputs/3-answer-key/bonus-marking-grouping/Check           
1087:  edOMRs/_MULTI_/colored                                      
1088:  INFO     Created :                                         file.py:79
1089:  outputs/3-answer-key/bonus-marking-grouping/Manua           
1090:  l                                                           
1091:  INFO     Created :                                         file.py:79
1092:  outputs/3-answer-key/bonus-marking-grouping/Manua           
1093:  l/MultiMarkedFiles                                          
1094:  INFO     Created :                                         file.py:79
1095:  outputs/3-answer-key/bonus-marking-grouping/Manua           
1096:  l/ErrorFiles                                                
1097:  INFO     Created :                                         file.py:90
...

1101:  outputs/3-answer-key/bonus-marking-grouping/Image           
1102:  Metrics                                                     
1103:  INFO     Created :                                         file.py:90
1104:  outputs/3-answer-key/bonus-marking-grouping/Evalu           
1105:  ations                                                      
1106:  INFO     Checking Files...                    directory_handler.py:32
1107:  INFO     Created new file:                    directory_handler.py:60
1108:  'outputs/3-answer-key/bonus-marking-                        
1109:  grouping/Results/Results_05AM.csv'                          
1110:  INFO     Created new file:                    directory_handler.py:60
1111:  'outputs/3-answer-key/bonus-marking-                        
1112:  grouping/Manual/MultiMarkedFiles.csv                        
1113:  '                                                           
1114:  INFO     Created new file:                    directory_handler.py:60
1115:  'outputs/3-answer-key/bonus-marking-                        
1116:  grouping/Manual/ErrorFiles.csv'                             
1117:  INFO                                                      entry.py:44
...

1595:  ckedOMRs/colored/IMG_20201116_150750830.jpg'                
1596:  INFO     Gray Stack level: 1 ['Input Image', 'Truncate    file.py:130
1597:  Threshold', 'Bounding Contour', 'Marked                     
1598:  Template']                                                  
1599:  INFO     Saved stack image to:                            file.py:136
1600:  outputs/3-answer-key/bonus-marking-grouping/Chec            
1601:  kedOMRs/stack/IMG_20201116_150750830_1_stack.jpg            
1602:  INFO     Colored Stack level: 1 ['Input Image', 'Marked   file.py:144
1603:  Template']                                                  
1604:  INFO     Saved colored stack image to:                    file.py:154
1605:  outputs/3-answer-key/bonus-marking-grouping/Chec            
1606:  kedOMRs/stack/colored/IMG_20201116_150750830_1_s            
1607:  tack.jpg                                                    
1608:  DEBUG    Closed file Results                  directory_handler.py:77
1609:  DEBUG    Closed file MultiMarked              directory_handler.py:77
1610:  DEBUG    Closed file Errors                   directory_handler.py:77
1611:  INFO                                                     entry.py:487
...

1625:  `outputs.show_image_level` in your config:                  
1626:  'samples/3-answer-key/bonus-marking-grouping/co             
1627:  nfig.json'                                                  
1628:  ------------------------------ Captured log call -------------------------------
1629:  INFO     src.utils.logger:validations.py:85 Loading config.json: samples/3-answer-key/bonus-marking-grouping/config.json
1630:  INFO     src.utils.logger:validations.py:50 Loading template.json: samples/3-answer-key/bonus-marking-grouping/template.json
1631:  INFO     src.utils.logger:validations.py:12 Loading evaluation.json: samples/3-answer-key/bonus-marking-grouping/evaluation.json
1632:  INFO     src.utils.logger:file.py:56 Checking Directories...
1633:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/colored
1634:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/stack
1635:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/stack/colored
1636:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/_MULTI_
1637:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/_MULTI_/colored
1638:  INFO     src.utils.logger:file.py:79 Created : outputs/3-answer-key/bonus-marking-grouping/Manual
1639:  INFO     src.utils.logger:file.py:79 Created : outputs/3-answer-key/bonus-marking-grouping/Manual/MultiMarkedFiles
1640:  INFO     src.utils.logger:file.py:79 Created : outputs/3-answer-key/bonus-marking-grouping/Manual/ErrorFiles
1641:  INFO     src.utils.logger:file.py:90 Created : outputs/3-answer-key/bonus-marking-grouping/Results
1642:  INFO     src.utils.logger:file.py:90 Created : outputs/3-answer-key/bonus-marking-grouping/ImageMetrics
1643:  INFO     src.utils.logger:file.py:90 Created : outputs/3-answer-key/bonus-marking-grouping/Evaluations
1644:  INFO     src.utils.logger:directory_handler.py:32 Checking Files...
1645:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/3-answer-key/bonus-marking-grouping/Results/Results_05AM.csv'
1646:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/3-answer-key/bonus-marking-grouping/Manual/MultiMarkedFiles.csv'
1647:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/3-answer-key/bonus-marking-grouping/Manual/ErrorFiles.csv'
1648:  INFO     src.utils.logger:entry.py:44 
...

1773:  parsed_destination_points=[[  0.   0.]
1774:  [277.   0.]
1775:  [277. 378.]
1776:  [  0. 378.]] 
1777:  warped_dimensions=(277, 378)
1778:  DEBUG    src.utils.logger:interpretation_pass.py:62 Thresholding: 	 file_level_fallback_threshold: 195.23 	global_std_THR: 10.39	
1779:  INFO     src.utils.logger:entry.py:333 (/3) Graded with score: 6.0	 Correct: 2 Incorrect: 8 Unmarked: 1 	 file: 'IMG_20201116_150750830.jpg'
1780:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/IMG_20201116_150750830.jpg'
1781:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/colored/IMG_20201116_150750830.jpg'
1782:  INFO     src.utils.logger:file.py:130 Gray Stack level: 1 ['Input Image', 'Truncate Threshold', 'Bounding Contour', 'Marked Template']
1783:  INFO     src.utils.logger:file.py:136 Saved stack image to: outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/stack/IMG_20201116_150750830_1_stack.jpg
1784:  INFO     src.utils.logger:file.py:144 Colored Stack level: 1 ['Input Image', 'Marked Template']
1785:  INFO     src.utils.logger:file.py:154 Saved colored stack image to: outputs/3-answer-key/bonus-marking-grouping/CheckedOMRs/stack/colored/IMG_20201116_150750830_1_stack.jpg
1786:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Results
1787:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file MultiMarked
1788:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Errors
1789:  INFO     src.utils.logger:entry.py:487 
1790:  INFO     src.utils.logger:entry.py:488 Total file(s) moved        : 0
1791:  INFO     src.utils.logger:entry.py:489 Total file(s) not moved    : 3
1792:  INFO     src.utils.logger:entry.py:490 --------------------------------
1793:  INFO     src.utils.logger:entry.py:491 Total file(s) processed    : 3 (Sum Tallied!)
1794:  INFO     src.utils.logger:entry.py:496 
1795:  Finished Checking 3 file(s) in 1 seconds i.e. ~0.0 minute(s).
1796:  INFO     src.utils.logger:entry.py:499 OMR Processing Rate        : 	 ~ 0.33 seconds/OMR
1797:  INFO     src.utils.logger:entry.py:502 OMR Processing Speed       : 	 ~ 180.0 OMRs/minute
1798:  INFO     src.utils.logger:entry.py:173 
1799:  Tip: To see some awesome visuals, increase `outputs.show_image_level` in your config: 'samples/3-answer-key/bonus-marking-grouping/config.json'
1800:  ___________________ test_run_answer_key_using_image_grouping ___________________
1801:  run_sample = <function run_sample_fixture.<locals>.run_sample at 0x7fd5a2a8ad40>
1802:  mocker = <pytest_mock.plugin.MockerFixture object at 0x7fd59e775250>
1803:  snapshot = dict({
1804:  'Manual/ErrorFiles.csv': '''
1805:  Empty DataFrame
...

1814:  sample_outputs = run_sample(mocker, sample_path)
1815:  assert snapshot == sample_outputs
1816:  output_relative_dir = f"outputs/{sample_path}/CheckedOMRs"
1817:  >       assert_image_snapshot(output_relative_dir, "angle-1.jpg", image_snapshot)
1818:  src/tests/test_all_samples.py:61: 
1819:  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
1820:  src/tests/utils.py:127: in assert_image_snapshot
1821:  image_snapshot(output_path, IMAGE_SNAPSHOTS_PATH.joinpath(image_path))
1822:  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
1823:  source_image_path = PosixPath('outputs/3-answer-key/using-image-grouping/CheckedOMRs/angle-1.jpg')
1824:  snapshot_path = PosixPath('src/tests/__image_snapshots__/angle-1.jpg')
1825:  def _image_snapshot(source_image_path, snapshot_path) -> None:
1826:  source_image_path, snapshot_path = Path(source_image_path), Path(snapshot_path)
1827:  config = request.config
1828:  update_snapshots = config.getoption("--image-snapshot-update")
1829:  show_on_fail = config.getoption("--show-images-on-fail")
1830:  source_image = open_image(source_image_path)
1831:  if not update_snapshots and snapshot_path.exists():
1832:  current_snapshot = open_image(snapshot_path)
1833:  # source_image, current_snapshot = extend_to_match_size(source_image, current_snapshot)
1834:  diff_score = image_diff(source_image, current_snapshot)
1835:  if diff_score != 0:
1836:  if show_on_fail is True:
1837:  cv2.imshow("diff", cv2.subtract(source_image, current_snapshot))
1838:  cv2.imshow("current_snapshot", current_snapshot)
1839:  # TODO: fix code is not waiting despite unmocking mocker
1840:  close_all_on_wait_key()
1841:  msg = f"{snapshot_path}: Snapshot does not match the image {source_image_path}"
1842:  >               raise AssertionError(msg)
1843:  E               AssertionError: src/tests/__image_snapshots__/angle-1.jpg: Snapshot does not match the image outputs/3-answer-key/using-image-grouping/CheckedOMRs/angle-1.jpg
1844:  src/tests/__fixtures__/pytest_image_snapshot.py:88: AssertionError
1845:  ----------------------------- Captured stdout call -----------------------------
...

1863:  outputs/3-answer-key/using-image-grouping/Checked           
1864:  OMRs/stack/colored                                          
1865:  INFO     Created :                                         file.py:70
1866:  outputs/3-answer-key/using-image-grouping/Checked           
1867:  OMRs/_MULTI_                                                
1868:  INFO     Created :                                         file.py:70
1869:  outputs/3-answer-key/using-image-grouping/Checked           
1870:  OMRs/_MULTI_/colored                                        
1871:  INFO     Created :                                         file.py:79
1872:  outputs/3-answer-key/using-image-grouping/Manual            
1873:  INFO     Created :                                         file.py:79
1874:  outputs/3-answer-key/using-image-grouping/Manual/           
1875:  MultiMarkedFiles                                            
1876:  INFO     Created :                                         file.py:79
1877:  outputs/3-answer-key/using-image-grouping/Manual/           
1878:  ErrorFiles                                                  
1879:  INFO     Created :                                         file.py:90
...

1881:  INFO     Created :                                         file.py:90
1882:  outputs/3-answer-key/using-image-grouping/ImageMe           
1883:  trics                                                       
1884:  INFO     Created :                                         file.py:90
1885:  outputs/3-answer-key/using-image-grouping/Evaluat           
1886:  ions                                                        
1887:  INFO     Checking Files...                    directory_handler.py:32
1888:  INFO     Created new file:                    directory_handler.py:60
1889:  'outputs/3-answer-key/using-image-gr                        
1890:  ouping/Results/Results_05AM.csv'                            
1891:  INFO     Created new file:                    directory_handler.py:60
1892:  'outputs/3-answer-key/using-image-gr                        
1893:  ouping/Manual/MultiMarkedFiles.csv'                         
1894:  INFO     Created new file:                    directory_handler.py:60
1895:  'outputs/3-answer-key/using-image-gr                        
1896:  ouping/Manual/ErrorFiles.csv'                               
1897:  INFO                                                      entry.py:44
...

2298:  INFO     (/1) Graded with score: 0.67     Correct: 16    entry.py:333
2299:  Incorrect: 58 Unmarked: 26          file:                   
2300:  'angle-1.jpg'                                               
2301:  INFO     Saving Image to                                  image.py:55
2302:  'outputs/3-answer-key/using-image-grouping/Check            
2303:  edOMRs/angle-1.jpg'                                         
2304:  INFO     Saving Image to                                  image.py:55
2305:  'outputs/3-answer-key/using-image-grouping/Check            
2306:  edOMRs/colored/angle-1.jpg'                                 
2307:  INFO     Note: Nothing to save for gray image. Stack      file.py:139
2308:  level: 0                                                    
2309:  INFO     Note: Nothing to save for colored image. Stack   file.py:161
2310:  level: 0                                                    
2311:  DEBUG    Closed file Results                  directory_handler.py:77
2312:  DEBUG    Closed file MultiMarked              directory_handler.py:77
2313:  DEBUG    Closed file Errors                   directory_handler.py:77
2314:  INFO                                                     entry.py:487
...

2328:  `outputs.show_image_level` in your config:                  
2329:  'samples/3-answer-key/using-image-grouping/conf             
2330:  ig.json'                                                    
2331:  ------------------------------ Captured log call -------------------------------
2332:  INFO     src.utils.logger:validations.py:85 Loading config.json: samples/3-answer-key/using-image-grouping/config.json
2333:  INFO     src.utils.logger:validations.py:50 Loading template.json: samples/3-answer-key/using-image-grouping/template.json
2334:  INFO     src.utils.logger:validations.py:12 Loading evaluation.json: samples/3-answer-key/using-image-grouping/evaluation.json
2335:  INFO     src.utils.logger:file.py:56 Checking Directories...
2336:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/using-image-grouping/CheckedOMRs/colored
2337:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/using-image-grouping/CheckedOMRs/stack
2338:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/using-image-grouping/CheckedOMRs/stack/colored
2339:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/using-image-grouping/CheckedOMRs/_MULTI_
2340:  INFO     src.utils.logger:file.py:70 Created : outputs/3-answer-key/using-image-grouping/CheckedOMRs/_MULTI_/colored
2341:  INFO     src.utils.logger:file.py:79 Created : outputs/3-answer-key/using-image-grouping/Manual
2342:  INFO     src.utils.logger:file.py:79 Created : outputs/3-answer-key/using-image-grouping/Manual/MultiMarkedFiles
2343:  INFO     src.utils.logger:file.py:79 Created : outputs/3-answer-key/using-image-grouping/Manual/ErrorFiles
2344:  INFO     src.utils.logger:file.py:90 Created : outputs/3-answer-key/using-image-grouping/Results
2345:  INFO     src.utils.logger:file.py:90 Created : outputs/3-answer-key/using-image-grouping/ImageMetrics
2346:  INFO     src.utils.logger:file.py:90 Created : outputs/3-answer-key/using-image-grouping/Evaluations
2347:  INFO     src.utils.logger:directory_handler.py:32 Checking Files...
2348:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/3-answer-key/using-image-grouping/Results/Results_05AM.csv'
2349:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/3-answer-key/using-image-grouping/Manual/MultiMarkedFiles.csv'
2350:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/3-answer-key/using-image-grouping/Manual/ErrorFiles.csv'
2351:  INFO     src.utils.logger:entry.py:44 
...

2383:  [604. 635.]
2384:  [ 36. 643.]] 
2385:  parsed_destination_points=[[  0.   0.]
2386:  [567.   0.]
2387:  [567. 497.]
2388:  [  0. 497.]] 
2389:  warped_dimensions=(567, 497)
2390:  DEBUG    src.utils.logger:interpretation_pass.py:62 Thresholding: 	 file_level_fallback_threshold: 177.5 	global_std_THR: 10	
2391:  INFO     src.utils.logger:entry.py:333 (/1) Graded with score: 0.67	 Correct: 16 Incorrect: 58 Unmarked: 26 	 file: 'angle-1.jpg'
2392:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/3-answer-key/using-image-grouping/CheckedOMRs/angle-1.jpg'
2393:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/3-answer-key/using-image-grouping/CheckedOMRs/colored/angle-1.jpg'
2394:  INFO     src.utils.logger:file.py:139 Note: Nothing to save for gray image. Stack level: 0
2395:  INFO     src.utils.logger:file.py:161 Note: Nothing to save for colored image. Stack level: 0
2396:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Results
2397:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file MultiMarked
2398:  DEBUG    src.utils.logger:directory_handler.py:77 Closed file Errors
2399:  INFO     src.utils.logger:entry.py:487 
2400:  INFO     src.utils.logger:entry.py:488 Total file(s) moved        : 0
2401:  INFO     src.utils.logger:entry.py:489 Total file(s) not moved    : 1
2402:  INFO     src.utils.logger:entry.py:490 --------------------------------
2403:  INFO     src.utils.logger:entry.py:491 Total file(s) processed    : 1 (Sum Tallied!)
2404:  INFO     src.utils.logger:entry.py:496 
2405:  Finished Checking 1 file(s) in 1 seconds i.e. ~0.0 minute(s).
2406:  INFO     src.utils.logger:entry.py:499 OMR Processing Rate        : 	 ~ 1.0 seconds/OMR
2407:  INFO     src.utils.logger:entry.py:502 OMR Processing Speed       : 	 ~ 60.0 OMRs/minute
2408:  INFO     src.utils.logger:entry.py:173 
2409:  Tip: To see some awesome visuals, increase `outputs.show_image_level` in your config: 'samples/3-answer-key/using-image-grouping/config.json'
2410:  ___________________________ test_run_template_shifts ___________________________
2411:  run_sample = <function run_sample_fixture.<locals>.run_sample at 0x7fd59e88e520>
2412:  mocker = <pytest_mock.plugin.MockerFixture object at 0x7fd5a1bc11d0>
2413:  snapshot = dict({
2414:  'alignment/Manual/ErrorFiles.csv': '''
2415:  Empty DataFrame
2416:  Columns: [file_id, input_path, output_path, sc...   D   C   D   A   A   C   B   C   D   C   A   B   C   B   D   A   A   C   A   B   D   C   D   A   C   B    A
2417:  ''',
2418:  })
2419:  def test_run_template_shifts(run_sample, mocker, snapshot) -> None:
2420:  sample_outputs = run_sample(mocker, "experimental/2-template-shifts")
2421:  >       assert snapshot == sample_outputs
2422:  E       AssertionError: assert [- snapshot] == [+ received]
2423:  E           dict({
2424:  E                ...
2425:  E                     file_id                                                   input_path                                                              output_path  score  Booklet_No q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 q16 q17 q18 q19 q20 q21 q22 q23 q24 q25 q26 q27 q28 q29 q30 q31 q32 q33 q34 q35 q36 q37 q38 q39 q40 q41 q42 q43 q44 q45 q46 q47 q48 q49 q50 q51 q52 q53 q54 q55 q56 q57 q58 q59 q60 q61 q62 q63 q64 q65 q66 q67 q68 q69 q70 q71 q72 q73 q74 q75 q76 q77 q78 q79 q80 q81 q82 q83 q84 q85 q86 q87 q88 q89 q90 q91 q92 q93 q94 q95 q96 q97 q98 q99 q100 q101 q102 q103 q104 q105 q106 q107 q108 q109 q110 q111 q112 q113 q114 q115 q116 q117 q118 q119 q120 q121 q122 q123 q124 q125 q126 q127 q128 q129 q130 q131 q132 q133 q134 q135 q136 q137 q138 q139 q140 q141 q142 q143 q144 q145 q146 q147 q148 q149 q150 q151 q152 q153 q154 q155 q156 q157 q158 q159 q160 q161 q162 q163 q164 q165 q166 q167 q168 q169 q170 q171 q172 q173 q174 q175 q176 q177 q178 q179 q180 q181 q182 q183 q184 q185 q186 q187 q1...
2426:  E         -     0   omr-1.png   samples/experimental/2-template-shifts/alignment/omr-1.png   outputs/experimental/2-template-shifts/alignment/CheckedOMRs/omr-1.png      0        1033  A  B  B  A  D  C  B  D  C   D   D   D   B   B   D   D   D   B   C   C   A   A   B   A   D   A   A   B   A   C   A   C   D   D   D           C   C   B   B   B       D       C   D       D   B   A   D   B   A   C   A   C   A   C   B   A   D   C   B   C   B   C   D   B   B   D   C   C   D   D   A   D   A   D   C   B   D   C   A   C       C   B   B       A   A   D       B   A       C   A    D    D    C    C    A    C    A    C    D    A    A    A    D    D    B    C    B    B    B    D    A    C    D    D    A    A    A    C    D    C    C    B    D    A    A    C    B         D    A    C    C    C                   A    C         D    A    B    A    A    C    A    D    B    B    A    D    A    B    C    A    C    D    D    D    C    A    C    A    C    D    A    A    A    D    A    B    A    B    C    B    A         B   ...
2427:  E         -     1  omr-2.jpeg  samples/experimental/2-template-shifts/alignment/omr-2.jpeg  outputs/experimental/2-template-shifts/alignment/CheckedOMRs/omr-2.jpeg      0      157344  B  A  C  D  A  D  D  A  C   A   A   B   C   A   A   C   A   B   A   D   C   C   A   D   D   C   C   C   A   C   C   B   B   D   D   C           C   B           D   A   A   A   A       A   C   C   C   D   C       A   B   C   D   B   C   C   C   D   A   B   B   B   D   D   B   B   C   D   B   D   A   B   A   B   C   A   C   A   C   D           A   B       B   C   D   A   D   D            C    D    B    B    A    A    D    D    B    A    B    B    C    C    D    D    C    A    D    C    D    C    C    B    C    D    C    D    A    B    D    C    B    D    B    B    A    D    A    B    D    B    B    C    A    D    A    C    A    C         B    C    A    B    B    D    D    D    B    A    D    D    A    D    D    C    B    B    D    C    B    A    C    D    A    D    D    A    C    A    B    D    C    C    C    A    D   ...
2428:  E         +     0   omr-1.png   samples/experimental/2-template-shifts/alignment/omr-1.png   outputs/experimental/2-template-shifts/alignment/CheckedOMRs/omr-1.png      0          13  A  B  B  A  D  C  B  D  C   D   D   D   B   B   D   D   D   B   C   C   A   A   B   A   D   A   A   B   A   C   A   C   D   D   D           C   C   B   B   B       D       C   D       D   B   A   D   B   A   C   A   C   A   C   B   A   D   C   B   C   B   C   D   B   B   D   C   C   D   D   A   D   A   D   C   B   D   C   A   C       C   B   B       A   A   D       B   A       C   A    D    D    C    C    A    C    A    C    D    A    A    A    D    D    B    C    B    B    B    D    A    C    D    D    A    A    A    C    D    C    C    B    D    A    A    C    B         D    A    C    C    C                   A    C         D    A    B    A    A    C    A    D    B    B    A    D    A    B    C    A    C    D    D    D    C    A    C    A    C    D    A    A    A    D    A    B    A    B    C    B    A         B   ...
2429:  E         +     1  omr-2.jpeg  samples/experimental/2-template-shifts/alignment/omr-2.jpeg  outputs/experimental/2-template-shifts/alignment/CheckedOMRs/omr-2.jpeg      0       15334  B  A  C  D  A  D  D  A  C   A   A   B   C   A   A   C   A   B   A   D   C   C   A   D   D   C   C   C   A   C   C   B   B   D   D   C           C   B           D   A   A   A   A       A   C   C   C   D   C       A   B   C   D   B   C   C   C   D   A   B   B   B   D   D   B   B   C   D   B   D   A   B   A   B   C   A   C   A   C   D           A   B       B   C   D   A   D   D            C    D    B    B    A    A    D    D    B    A    B    B    C    C    D    D    C    A    D    C    D    C    C    B    C    D    C    D    A    B    D    C    B    D    B    B    A    D         B    D    B    B    C    A    D         C         C         B    C    A    B    B    D    D    D    B    A    D    D    A    D    D    C    B    B    D    C    B    A    C    D    A    D    D    A    C    A    B    D    C    C    C    A    D   ...
2430:  E             ''',
2431:  E            ...
2432:  E           })
2433:  src/tests/test_all_samples.py:87: AssertionError
2434:  ----------------------------- Captured stdout call -----------------------------
...

2450:  ick-sheet/CheckedOMRs/stack/colored                         
2451:  INFO     Created :                                         file.py:70
2452:  outputs/experimental/2-template-shifts/colored-th           
2453:  ick-sheet/CheckedOMRs/_MULTI_                               
2454:  INFO     Created :                                         file.py:70
2455:  outputs/experimental/2-template-shifts/colored-th           
2456:  ick-sheet/CheckedOMRs/_MULTI_/colored                       
2457:  INFO     Created :                                         file.py:79
2458:  outputs/experimental/2-template-shifts/colored-th           
2459:  ick-sheet/Manual                                            
2460:  INFO     Created :                                         file.py:79
2461:  outputs/experimental/2-template-shifts/colored-th           
2462:  ick-sheet/Manual/MultiMarkedFiles                           
2463:  INFO     Created :                                         file.py:79
2464:  outputs/experimental/2-template-shifts/colored-th           
2465:  ick-sheet/Manual/ErrorFiles                                 
2466:  INFO     Created :                                         file.py:90
...

2471:  ick-sheet/ImageMetrics                                      
2472:  INFO     Created :                                         file.py:90
2473:  outputs/experimental/2-template-shifts/colored-th           
2474:  ick-sheet/Evaluations                                       
2475:  INFO     Checking Files...                    directory_handler.py:32
2476:  INFO     Created new file:                    directory_handler.py:60
2477:  'outputs/experimental/2-template-shi                        
2478:  fts/colored-thick-sheet/Results/Resu                        
2479:  lts_05AM.csv'                                               
2480:  INFO     Created new file:                    directory_handler.py:60
2481:  'outputs/experimental/2-template-shi                        
2482:  fts/colored-thick-sheet/Manual/Multi                        
2483:  MarkedFiles.csv'                                            
2484:  INFO     Created new file:                    directory_handler.py:60
2485:  'outputs/experimental/2-template-shi                        
2486:  fts/colored-thick-sheet/Manual/Error                        
2487:  Files.csv'                                                  
...

2575:  INFO     (/1) Processed file: 'rgb-100-gsm.jpg'          entry.py:341
2576:  INFO     Saving Image to                                  image.py:55
2577:  'outputs/experimental/2-template-shifts/colored-            
2578:  thick-sheet/CheckedOMRs/rgb-100-gsm.jpg'                    
2579:  INFO     Gray Stack level: 1 ['Input Image', 'Truncate    file.py:130
2580:  Threshold', 'Bounding Contour', 'Marked                     
2581:  Template']                                                  
2582:  INFO     Saved stack image to:                            file.py:136
2583:  outputs/experimental/2-template-shifts/colored-t            
2584:  hick-sheet/CheckedOMRs/stack/rgb-100-gsm_1_stack            
2585:  .jpg                                                        
2586:  INFO     Note: Nothing to save for colored image. Stack   file.py:161
2587:  level: 1                                                    
2588:  DEBUG    Closed file Results                  directory_handler.py:77
2589:  DEBUG    Closed file MultiMarked              directory_handler.py:77
2590:  DEBUG    Closed file Errors                   directory_handler.py:77
2591:  INFO                                                     entry.py:487
...

2620:  in-sheet/CheckedOMRs/stack/colored                          
2621:  INFO     Created :                                         file.py:70
2622:  outputs/experimental/2-template-shifts/xeroxed-th           
2623:  in-sheet/CheckedOMRs/_MULTI_                                
2624:  INFO     Created :                                         file.py:70
2625:  outputs/experimental/2-template-shifts/xeroxed-th           
2626:  in-sheet/CheckedOMRs/_MULTI_/colored                        
2627:  INFO     Created :                                         file.py:79
2628:  outputs/experimental/2-template-shifts/xeroxed-th           
2629:  in-sheet/Manual                                             
2630:  INFO     Created :                                         file.py:79
2631:  outputs/experimental/2-template-shifts/xeroxed-th           
2632:  in-sheet/Manual/MultiMarkedFiles                            
2633:  INFO     Created :                                         file.py:79
2634:  outputs/experimental/2-template-shifts/xeroxed-th           
2635:  in-sheet/Manual/ErrorFiles                                  
2636:  INFO     Created :                                         file.py:90
...

2641:  in-sheet/ImageMetrics                                       
2642:  INFO     Created :                                         file.py:90
2643:  outputs/experimental/2-template-shifts/xeroxed-th           
2644:  in-sheet/Evaluations                                        
2645:  INFO     Checking Files...                    directory_handler.py:32
2646:  INFO     Created new file:                    directory_handler.py:60
2647:  'outputs/experimental/2-template-shi                        
2648:  fts/xeroxed-thin-sheet/Results/Resul                        
2649:  ts_05AM.csv'                                                
2650:  INFO     Created new file:                    directory_handler.py:60
2651:  'outputs/experimental/2-template-shi                        
2652:  fts/xeroxed-thin-sheet/Manual/MultiM                        
2653:  arkedFiles.csv'                                             
2654:  INFO     Created new file:                    directory_handler.py:60
2655:  'outputs/experimental/2-template-shi                        
2656:  fts/xeroxed-thin-sheet/Manual/ErrorF                        
2657:  iles.csv'                                                   
...

2800:  INFO     (/1) Processed file: 'grayscale-80-gsm.jpg'     entry.py:341
2801:  INFO     Saving Image to                                  image.py:55
2802:  'outputs/experimental/2-template-shifts/xeroxed-            
2803:  thin-sheet/CheckedOMRs/grayscale-80-gsm.jpg'                
2804:  INFO     Gray Stack level: 1 ['Input Image', 'Truncate    file.py:130
2805:  Threshold', 'Bounding Contour', 'Marked                     
2806:  Template']                                                  
2807:  INFO     Saved stack image to:                            file.py:136
2808:  outputs/experimental/2-template-shifts/xeroxed-t            
2809:  hin-sheet/CheckedOMRs/stack/grayscale-80-gsm_1_s            
2810:  tack.jpg                                                    
2811:  INFO     Note: Nothing to save for colored image. Stack   file.py:161
2812:  level: 1                                                    
2813:  DEBUG    Closed file Results                  directory_handler.py:77
2814:  DEBUG    Closed file MultiMarked              directory_handler.py:77
2815:  DEBUG    Closed file Errors                   directory_handler.py:77
2816:  INFO                                                     entry.py:487
...

2848:  CheckedOMRs/stack/colored                                   
2849:  INFO     Created :                                         file.py:70
2850:  outputs/experimental/2-template-shifts/alignment/           
2851:  CheckedOMRs/_MULTI_                                         
2852:  INFO     Created :                                         file.py:70
2853:  outputs/experimental/2-template-shifts/alignment/           
2854:  CheckedOMRs/_MULTI_/colored                                 
2855:  INFO     Created :                                         file.py:79
2856:  outputs/experimental/2-template-shifts/alignment/           
2857:  Manual                                                      
2858:  INFO     Created :                                         file.py:79
2859:  outputs/experimental/2-template-shifts/alignment/           
2860:  Manual/MultiMarkedFiles                                     
2861:  INFO     Created :                                         file.py:79
2862:  outputs/experimental/2-template-shifts/alignment/           
2863:  Manual/ErrorFiles                                           
2864:  INFO     Created :                                         file.py:90
...

2869:  ImageMetrics                                                
2870:  INFO     Created :                                         file.py:90
2871:  outputs/experimental/2-template-shifts/alignment/           
2872:  Evaluations                                                 
2873:  INFO     Checking Files...                    directory_handler.py:32
2874:  INFO     Created new file:                    directory_handler.py:60
2875:  'outputs/experimental/2-template-shi                        
2876:  fts/alignment/Results/Results_05AM.c                        
2877:  sv'                                                         
2878:  INFO     Created new file:                    directory_handler.py:60
2879:  'outputs/experimental/2-template-shi                        
2880:  fts/alignment/Manual/MultiMarkedFile                        
2881:  s.csv'                                                      
2882:  INFO     Created new file:                    directory_handler.py:60
2883:  'outputs/experimental/2-template-shi                        
2884:  fts/alignment/Manual/ErrorFiles.csv'                        
2885:  INFO                                                      entry.py:44
...

9926:  'D', 'q174': 'D', 'q39': 'C', 'q199': '',                   
9927:  'q71': 'B', 'q80': 'B', 'q198': '', 'q102':                 
9928:  'B', 'q4': 'D', 'q178': 'A', 'q93': 'C', 'q87':             
9929:  '', 'q1': 'B', 'q177': 'D', 'q183': 'C',                    
9930:  'q153': 'A', 'q16': 'C', 'q10': 'A'}                        
9931:  INFO     (/2) Processed file: 'omr-2.jpeg'               entry.py:341
9932:  INFO     Saving Image to                                  image.py:55
9933:  'outputs/experimental/2-template-shifts/alignmen            
9934:  t/CheckedOMRs/omr-2.jpeg'                                   
9935:  INFO     Note: Nothing to save for gray image. Stack      file.py:139
9936:  level: 0                                                    
9937:  INFO     Note: Nothing to save for colored image. Stack   file.py:161
9938:  level: 0                                                    
9939:  DEBUG    Closed file Results                  directory_handler.py:77
9940:  DEBUG    Closed file MultiMarked              directory_handler.py:77
9941:  DEBUG    Closed file Errors                   directory_handler.py:77
9942:  INFO                                                     entry.py:487
...

9945:  INFO     --------------------------------                entry.py:490
9946:  INFO     Total file(s) processed    : 2 (Sum Tallied!)   entry.py:491
9947:  INFO                                                     entry.py:506
9948:  Total script time          : 1 seconds                      
9949:  ------------------------------ Captured log call -------------------------------
9950:  INFO     src.utils.logger:validations.py:85 Loading config.json: samples/experimental/2-template-shifts/config.json
9951:  INFO     src.utils.logger:validations.py:50 Loading template.json: samples/experimental/2-template-shifts/colored-thick-sheet/template.json
9952:  INFO     src.utils.logger:file.py:56 Checking Directories...
9953:  INFO     src.utils.logger:file.py:70 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/colored
9954:  INFO     src.utils.logger:file.py:70 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/stack
9955:  INFO     src.utils.logger:file.py:70 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/stack/colored
9956:  INFO     src.utils.logger:file.py:70 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/_MULTI_
9957:  INFO     src.utils.logger:file.py:70 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/_MULTI_/colored
9958:  INFO     src.utils.logger:file.py:79 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/Manual
9959:  INFO     src.utils.logger:file.py:79 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/Manual/MultiMarkedFiles
9960:  INFO     src.utils.logger:file.py:79 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/Manual/ErrorFiles
9961:  INFO     src.utils.logger:file.py:90 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/Results
9962:  INFO     src.utils.logger:file.py:90 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/ImageMetrics
9963:  INFO     src.utils.logger:file.py:90 Created : outputs/experimental/2-template-shifts/colored-thick-sheet/Evaluations
9964:  INFO     src.utils.logger:directory_handler.py:32 Checking Files...
9965:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/experimental/2-template-shifts/colored-thick-sheet/Results/Results_05AM.csv'
9966:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/experimental/2-template-shifts/colored-thick-sheet/Manual/MultiMarkedFiles.csv'
9967:  INFO     src.utils.logger:directory_handler.py:60 Created new file: 'outputs/experimental/2-template-shifts/colored-thick-sheet/Manual/ErrorFiles.csv'
9968:  INFO     src.utils.logger:entry.py:44 
...

9989:  parsed_destination_points=[[  0.   0.]
9990:  [465.   0.]
9991:  [465. 683.]
9992:  [  0. 683.]] 
9993:  warped_dimensions=(465, 683)
9994:  DEBUG    src.utils.logger:interpretation_pass.py:62 Thresholding: 	 file_level_fallback_threshold: 166.41 	global_std_THR: 16.69	
9995:  INFO     src.utils.logger:entry.py:340 Read Response: 
9996:  {'q57': 'B', 'q78': '', 'q40': 'A', 'q20': 'D', 'q8': '', 'q92': 'A', 'q53': 'D', 'q67': 'B', 'q9': 'A', 'q56': '', 'q12': 'D', 'q94': 'A', 'q86': '', 'q37': 'D', 'q41': '', 'q95': '', 'q77': 'A', 'q62': 'C', 'q27': '', 'q96': '', 'q48': 'A', 'q84': 'C', 'q68': 'C', 'q74': 'D', 'q66': 'A', 'q30': 'D', 'q2': 'D', 'q75': 'C', 'q54': 'B', 'q3': 'A', 'q6': 'C', 'q100': 'A', 'q51': 'C', 'q28': 'B', 'q97': 'A', 'q23': 'D', 'q36': 'C', 'q42': 'A', 'q65': 'C', 'q18': 'D', 'q59': 'D', 'q15': 'A', 'q45': 'B', 'q22': 'C', 'q76': 'D', 'q88': '', 'q89': 'D', 'q70': '', 'q17': 'A', 'q58': 'C', 'q83': 'D', 'q7': 'B', 'q21': 'D', 'q5': 'C', 'q63': 'C', 'q38': '', 'q14': 'D', 'q73': 'D', 'q49': 'C', 'q43': 'C', 'q69': '', 'q98': 'C', 'q46': 'C', 'q47': 'A', 'q33': '', 'q60': '', 'q55': 'C', 'q26': 'D', 'q52': '', 'q25': 'D', 'q64': '', 'q79': '', 'q72': '', 'q91': 'D', 'q24': 'D', 'q99': 'B', 'q81': '', 'q85': 'C', 'q61': '', 'q44': 'C', 'q50': '', 'q31': 'D', 'q19': 'B', 'q32': 'C', 'q29': 'A', 'q90': 'C', 'q82': 'B', 'q39': '', 'q13': 'A', 'q71': '', 'q80': 'B', 'q4': '', 'q93': '', 'q87': 'D', 'q1': 'D', 'q11': 'C', 'q35': '', 'q34': 'B', 'q16': 'C', 'q10': 'C'}
9997:  INFO     src.utils.logger:entry.py:341 (/1) Processed file: 'rgb-100-gsm.jpg'
9998:  INFO     src.utils.logger:image.py:55 Saving Image to 'outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/rgb-100-gsm.jpg'
9999:  INFO     src.utils.logger:file.py:130 Gray Stack level: 1 ['Input Image', 'Truncate Threshold', 'Bounding Contour', 'Marked Template']
10000:  INFO     src.utils.logger:file.py:136 Saved stack image to: outputs/experimental/2-template-shifts/colored-thick-sheet/CheckedOMRs/stack/rgb-100-gsm_1_stack.jpg
10001:  INFO   ...

@fph
Copy link

fph commented Feb 1, 2026

Thanks! The updates look great. Is this new version ready to test / use? Do you have an idea when they will be merged?

@paolini and I have been using v1 for a project related to the Italian math Olympiad; it would be great to have all these new features in main (and maybe we can contribute some code back to the project once we're using v2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Support for Set mapping in the evaluation schema

7 participants